package com.springboot.wisdom.mqtt.handler;

import cn.hutool.core.date.DateTime;
import com.alibaba.fastjson2.JSONObject;
import com.springboot.wisdom.mqtt.config.MqttConfigurationProperties;
import com.springboot.wisdom.mqtt.gateway.MqttGateway;
import com.springboot.wisdom.mqtt.mapper.HardwareDeviceMapper;
import com.springboot.wisdom.mqtt.service.HardwareDeviceLogService;
import com.springboot.wisdom.mqtt.service.HardwareDeviceService;
import com.springboot.wisdom.serviceApi.mqtt.constant.MqttDeviceStatusEnum;
import com.springboot.wisdom.serviceApi.mqtt.constant.MqttDeviceTypeEnum;
import com.springboot.wisdom.serviceApi.mqtt.model.dto.HardwareDeviceDTO;
import com.springboot.wisdom.serviceApi.mqtt.model.dto.MqttMsg;
import com.springboot.wisdom.serviceApi.mqtt.model.entity.HardwareDeviceDO;
import com.springboot.wisdom.serviceApi.mqtt.model.entity.HardwareDeviceLogDO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHandler;
import org.springframework.messaging.MessageHeaders;
import org.springframework.messaging.MessagingException;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.annotation.PostConstruct;
import java.util.Objects;


/**
 * mqtt 订阅消息类。【接收mqtt发送过来的数据】
 */
@Component
@Slf4j
public class ReceiverMessageHandler implements MessageHandler {

    @Autowired
    private MqttConfigurationProperties mqttConfigurationProperties;
    private String[] subTopic;        // 订阅主题列表。
    private String connect;         // 设备连接。
    private String deviceInit;      // 设备初始化/设备注册。
    private String liveData;        // 实时数据。
    private String[] pubTopic;        // 发布主题列表。
    private String deviceResponseInit;  // 设备初始化注册响应。


    @Autowired
    private HardwareDeviceService hardwareDeviceService;

    @Autowired
    private HardwareDeviceMapper hardwareDeviceMapper;

    @Autowired
    private MqttGateway mqttGateway;

    @Autowired
    private HardwareDeviceLogService hardwareDeviceLogService;


    /**
     * 该方法用于 @Autowired注入 后的操作。
     * <p>
     * 执行顺序：构造方法 → 普通变量初始化 → @Autowired注入 → @PostConstruct方法。
     */
    @PostConstruct
    public void init() {
        // 此时所有依赖（包括@Autowired）已完成注入。
        subTopic = mqttConfigurationProperties.getSubTopic().split(",");
        pubTopic = mqttConfigurationProperties.getPubTopic().split(",");
        // 订阅主题。
        connect = subTopic[0];
        deviceInit = subTopic[1];
        liveData = subTopic[2];
        // 发布主题。
        deviceResponseInit = pubTopic[0];
    }


    /**
     * 处理mqtt请求。
     *
     * @param message 接收到的数据报文。
     * @throws MessagingException
     */
    @Override
    public void handleMessage(Message<?> message) throws MessagingException {
        Object payload = message.getPayload();
        System.out.println("payload = " + payload);
        System.out.println("message = " + message);

        MessageHeaders headers = message.getHeaders();
        // 主题名称。
        String topicName = Objects.requireNonNull(headers.get("mqtt_receivedTopic")).toString();
        System.out.println("topicName = " + topicName);

        MqttMsg mqttMsg = JSONObject.parseObject(payload.toString(), MqttMsg.class);

        // 设备类型。
        if (mqttMsg.getType() == null || mqttMsg.getStatus() == null) {
            log.warn("设备类型：" + mqttMsg.getType() + "不支持！" + "或 设备状态：" + mqttMsg.getStatus() + " 不支持！");
            return;
        }

        if (deviceInit.equalsIgnoreCase(topicName)) {                   // 设备注册。
            System.out.println("mqttMsg = " + mqttMsg);
            System.out.println("设备初始化...........");
            // 已注册。
            HardwareDeviceDO deviceById = hardwareDeviceService.getById(mqttMsg.getId());
            if (deviceById != null) {
                log.warn("设备" + mqttMsg.getId() + "已注册！");
                return;
            }
            // 非 中控单片机的配置判断。
            if (MqttDeviceTypeEnum.SINGLECHIP != mqttMsg.getType()) {
                if (StringUtils.isEmpty(mqttMsg.getData())) {
                    log.warn("设备所属ID 为空！");
                    return;
                }
                HardwareDeviceDO deviceFromId = hardwareDeviceService.getById(mqttMsg.getData());
                if (deviceFromId == null) {
                    log.warn("设备所属ID 不存在！");
                    return;
                }
            }
            // 中控单片机。
            if (MqttDeviceTypeEnum.SINGLECHIP == mqttMsg.getType() && StringUtils.isEmpty(mqttMsg.getId())){
                log.warn("设备 Mac 为空！");
                return;
            }
            // 连接类型。
            switch (mqttMsg.getType()) {
                case SINGLECHIP:    // 单片机。
                    mqttMsg.setStatus(MqttDeviceStatusEnum.REGISTER);
                    break;
                case LED:           // 灯。
                case KEY:           // 按键。
                case BEEP:          // 蜂鸣器。
                case CAMERA:        // 照相机。
                    mqttMsg.setStatus(MqttDeviceStatusEnum.OFF);
                    break;
                case HUMIDITY:      // 湿度。
                case TEMPERATURE:   // 温度。
                    mqttMsg.setStatus(MqttDeviceStatusEnum.ON);
                    break;
                case NONE:          // 无设备。
            }

            HardwareDeviceDO dto = HardwareDeviceDTO.builder()
                    .deviceId(mqttMsg.getId()).deviceName(mqttMsg.getName())
                    .deviceType(mqttMsg.getType().getDesc())
                    .deviceStatus(mqttMsg.getStatus().getDesc())
                    .deviceFromId(MqttDeviceTypeEnum.SINGLECHIP == mqttMsg.getType() ? null : mqttMsg.getData())
                    .remark(mqttMsg.getRemark()).updateTime(DateTime.now()).build();
            System.out.println("dto = " + dto);
            hardwareDeviceService.save(dto);
            hardwareDeviceLogService.save(
                    new HardwareDeviceLogDO(null, dto.getDeviceId(), dto.getDeviceStatus(), null)
            );
            mqttMsg.setId(dto.getDeviceId());
            // 在响应的主题后，加上 中控单片机 的 Mac 地址作为主题。
            mqttGateway.sendMsgMqtt(
                    deviceResponseInit
                            + "/" + (MqttDeviceTypeEnum.SINGLECHIP == mqttMsg.getType()
                            ? mqttMsg.getId() : mqttMsg.getData())
                    , JSONObject.toJSONString(mqttMsg));

        } else if (connect.equalsIgnoreCase(topicName)) {              // 中控台单片机设备开机【心跳】。
            System.out.println("设备连接............");
            // 空 JSON，则为心跳。
            if (StringUtils.isEmpty(mqttMsg.getId()) || mqttMsg.getType() == null || mqttMsg.getStatus() == null) {
                return;
            }
            HardwareDeviceDO deviceById = hardwareDeviceService.getById(mqttMsg.getId());
            if (deviceById == null) {
                log.warn("ID：" + mqttMsg.getId() + "未注册！");
                return;
            }
            HardwareDeviceDO dto = HardwareDeviceDTO.builder().build();
            switch (mqttMsg.getType()) {
                case SINGLECHIP:    // 中控台单片机。
                    dto = HardwareDeviceDTO.builder()
                            .deviceId(mqttMsg.getId())
                            .deviceType(mqttMsg.getType().getDesc())
                            .deviceStatus(MqttDeviceStatusEnum.ON.getDesc())
                            .updateTime(DateTime.now()).build();
                    hardwareDeviceLogService.save(
                            new HardwareDeviceLogDO(null, dto.getDeviceId(), dto.getDeviceStatus(), null)
                    );
                    break;
            }
            hardwareDeviceLogService.save(
                    new HardwareDeviceLogDO(null, dto.getDeviceId(), dto.getDeviceStatus(), null)
            );
        } else if (liveData.equalsIgnoreCase(topicName)) {      // 实时数据【只对设备上下线操作进行存储】。
            // 设备操作。
            switch (mqttMsg.getType()) {
                case SINGLECHIP:    // 单片机。
                case LED:           // 灯。
                case KEY:           // 按键。
                case BEEP:          // 蜂鸣器。
                case CAMERA:        // 照相机。
                    HardwareDeviceDO dto = HardwareDeviceDTO.builder()
                            .deviceId(mqttMsg.getId()).deviceName(mqttMsg.getName())
                            .deviceType(mqttMsg.getType().getDesc())
                            .deviceStatus(mqttMsg.getStatus().getDesc())
                            .remark(mqttMsg.getRemark()).updateTime(DateTime.now()).build();

                    System.out.println("dto = " + dto);
                    hardwareDeviceService.saveOrUpdate(dto);
                    hardwareDeviceLogService.save(
                            new HardwareDeviceLogDO(null, dto.getDeviceId(), dto.getDeviceStatus(), null)
                    );
                    break;
                case HUMIDITY:      // 湿度。
                case TEMPERATURE:   // 温度。
                case NONE:          // 无设备。
                    break;
            }
            System.out.println("mqttMsg = " + mqttMsg);
            System.out.println("实时数据...........");
        } else {

        }
    }


}
